package pub.developers.forum.portal.controller.rest;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import pub.developers.forum.api.model.PageRequestModel;
import pub.developers.forum.api.model.PageResponseModel;
import pub.developers.forum.api.model.ResultModel;
import pub.developers.forum.api.request.article.ArticleInformRequest;
import pub.developers.forum.api.request.file.FileUploadImgRequest;
import pub.developers.forum.api.request.user.*;
import pub.developers.forum.api.response.article.ArticleLoveResponse;
import pub.developers.forum.api.response.user.UserInfoResponse;
import pub.developers.forum.api.service.FileApiService;
import pub.developers.forum.api.service.UserApiService;
import pub.developers.forum.common.constant.Constant;
import pub.developers.forum.common.enums.ErrorCodeEn;
import pub.developers.forum.common.support.CheckUtil;
import pub.developers.forum.facade.support.ResultModelUtil;
import pub.developers.forum.portal.support.WebUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.List;
import java.util.Set;

import static pub.developers.forum.common.enums.ErrorCodeEn.MORE_MAX;

@RestController
@RequestMapping("/user-rest")
public class UserRestController {

    @Resource
    private UserApiService userApiService;

    @Resource
    private FileApiService fileApiService;

    @Value("${wechat.appid}")
    private String appId;

     @Value("${wechat.appSecret}")
     String appSecret;

    @Value("${wechat.appid1}")
    private String appId1;

    @Value("${wechat.appSecret1}")
    String appSecret1;

    @Value("${wechat.appid2}")
    private String appId2;

    @Value("${wechat.appSecret2}")
    String appSecret2;

    // .css;.js;.png;.jpeg;.jpg;.woff2;.html;.ico;.gif;.bmp;.svg;.woff;.map
    private static final Set<String> ALLOW_TYPES = Sets.newHashSet("png", "jpeg", "jpg", "ico", "gif", "bmp", "svg");

    @PostMapping("/register")
    public ResultModel<String> register(@RequestBody UserRegisterRequest request, HttpServletRequest servletRequest, HttpServletResponse response) throws Exception {
        request.setIp(WebUtil.requestIp(servletRequest));
        request.setUa(WebUtil.requestUa(servletRequest));
        ResultModel<String> resultModel = userApiService.register(request);

        WebUtil.cookieAddSid(response, resultModel.getData());

        return resultModel;
    }

    @PostMapping("/login")
    public ResultModel<String> login(@RequestBody UserEmailLoginRequest request, HttpServletRequest servletRequest, HttpServletResponse response) throws Exception {
        request.setIp(WebUtil.requestIp(servletRequest));
        request.setUa(WebUtil.requestUa(servletRequest));
        ResultModel<String> resultModel =  userApiService.emailLogin(request);

        WebUtil.cookieAddSid(response, resultModel.getData());

        return resultModel;
    }

    @GetMapping("/wxLogin")
    public ResultModel<String> wxLogin(@RequestParam String code ,@RequestParam String type,HttpServletRequest servletRequest,HttpServletResponse response) {
        String url = "";
        if (type.equals("mini1")){
           url = "https://api.weixin.qq.com/sns/jscode2session"+
                    "?appid="+appId1+
                    "&secret=" + appSecret1 +
                    "&js_code=" + code +
                    "&grant_type=authorization_code";
        }else if(type.equals("mini2")){
           url = "https://api.weixin.qq.com/sns/jscode2session"+
                    "?appid="+appId2+
                    "&secret=" + appSecret2 +
                    "&js_code=" + code +
                    "&grant_type=authorization_code";
        }

        // 发起HTTP请求，获取微信用户的OpenID和Session Key
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> wechatResponse = restTemplate.getForEntity(url, String.class);

        if (wechatResponse.getStatusCode() == HttpStatus.OK) {
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode jsonNode = objectMapper.readTree(wechatResponse.getBody());

                if (jsonNode.has("errmsg")){
                    String errMsg = jsonNode.get("errmsg").asText();
                    String errCode = jsonNode.get("errcode").asText();
                    if (Integer.valueOf(errCode) != 0 ){
                        return ResultModelUtil.fail(Integer.valueOf(errCode),errMsg);
                    }
                }

                String openid = jsonNode.get("openid").asText();
                String unionid = jsonNode.get("unionid").asText();
                System.out.println(unionid);
                String sessionKey = jsonNode.get("session_key").asText();

                // 返回成功响应
                return ResultModelUtil.success(unionid);
            } catch (Exception e) {
                // 处理异常，返回失败响应
                return ResultModelUtil.fail(80007992,"登录失败");
            }
        } else {
            // 处理HTTP请求失败，返回失败响应
            return ResultModelUtil.fail(80007993,"无效的code");
        }

    }

    @GetMapping("/logout")
    public ResultModel logout(HttpServletResponse response, HttpServletRequest request) throws Exception {

        // 删除 cookie 中登录凭证
        WebUtil.cookieDelSid(response);

        return ResultModelUtil.success();
    }

    @PostMapping("/wxLogin2")
    public ResultModel<String> wxLogin(@RequestBody UserWxLoginRequest request, HttpServletRequest servletRequest, HttpServletResponse response) throws Exception {
//       request.setIp(WebUtil.requestIp(servletRequest));
//       request.setUa(WebUtil.requestUa(servletRequest));

       if (request.getOpenid()  != null){
           ResultModel<String> resultModel = userApiService.wxLogin(request);

           WebUtil.cookieAddSid(response,resultModel.getData());

           return resultModel;

        }
     return ResultModelUtil.fail(80007992,"登陆失败");
    }

    @PostMapping("/signOut")
    public ResultModel signOut(HttpServletRequest request,HttpServletResponse response){
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));
        return userApiService.signOut();
    }

    @PostMapping("/update-info")
    public ResultModel updateInfo(@RequestBody UserUpdateInfoRequest updateInfoRequest, HttpServletRequest request) throws UnsupportedEncodingException {
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));

        return userApiService.updateInfo(updateInfoRequest);
    }

    @PostMapping("/update-headimg")
    public ResultModel ResultModelupdateHeadImg(MultipartFile file, HttpServletRequest request)throws IOException {
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));
        //获取文件的内容
        InputStream is = file.getInputStream();
        //获取原始文件名
        String originalFilename = file.getOriginalFilename();
        ResultModel<String> linkFilename =  updateHeadimg(file,originalFilename,request);
        return userApiService.updateHeadImg(linkFilename.getData());
    }



    // 修改头像
    private ResultModel<String> updateHeadimg(MultipartFile file, String originalFilename, HttpServletRequest request) {
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));

        String fileType = file.getContentType();
        boolean isAllowType = false;
        for (String allowType : ALLOW_TYPES) {
            if (fileType != null && fileType.contains(allowType)) {
                isAllowType = true;
                break;
            }
        }
        CheckUtil.isFalse(isAllowType, ErrorCodeEn.FILE_UPLOAD_NOT_SUPPORT_IMG_TYPE);

        FileUploadImgRequest uploadImgRequest = null;
        try {
            uploadImgRequest = FileUploadImgRequest.builder()
                    .base64(file.getBytes())
                    .fileName(originalFilename)
                    .build();
        } catch (Exception e) {
            CheckUtil.isTrue(true, ErrorCodeEn.FILE_UPLOAD_FAIL);
        }

        return fileApiService.uploadImg(uploadImgRequest);
    }

    // 修改密码
    @PostMapping("/update-pwd")
    public ResultModel updatePwd(@RequestBody UserUpdatePwdRequest updatePwdRequest, HttpServletRequest request) {
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));

        return userApiService.updatePwd(updatePwdRequest);
    }


    // 关注
    @PostMapping("/follow/{followed}")
    public ResultModel follow(@PathVariable("followed") Long followed, HttpServletRequest request) throws Exception {
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));

        return userApiService.follow(followed);
    }

    @PostMapping("/cancel-follow/{followed}")
    public ResultModel cancelFollow(@PathVariable("followed") Long followed, HttpServletRequest request) throws Exception {
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));

        return userApiService.cancelFollow(followed);
    }


    //获取我的粉丝列表
    @PostMapping("/get-fans")
    public ResultModel getFans(HttpServletRequest request)
    {
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request)); //验证用户登录状态
        return userApiService.queryFans();
    }

    // 获取我的关注
    @PostMapping("/get-follower")
    public ResultModel<PageResponseModel<UserInfoResponse>> getFollow(@RequestBody PageRequestModel pageRequestModel, HttpServletRequest request){
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));
        return userApiService.queryFollower(pageRequestModel);
    }

    //获取我的点赞列表(谁点赞了我的哪一篇帖子)
    @PostMapping("/getPostsFollower")
    public ResultModel getLikePosts(HttpServletRequest request)
    {
        //验证用户登录状态
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY , WebUtil.cookieGetSid(request));
        return userApiService.queryFollowList();
    }

    //获取我的点赞列表(谁点赞了我的哪一条评论)
    @PostMapping("/getCommentFollower")
    public ResultModel getLikeComment(HttpServletRequest request)
    {
        //验证用户登录状态
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY , WebUtil.cookieGetSid(request));
        return userApiService.queryFollowCommentList();
    }


    //发送邮件
    @RequestMapping("/getCheckCode")
    @ResponseBody
    public ResultModel getCheckCode(String email)
    {
        Long codeL = System.nanoTime();
        String codeStr = Long.toString(codeL);
        String verifyCode = codeStr.substring(codeStr.length() - 6);
        try {
            userApiService.sendEmail(email, "XIUXIUDA登录验证码", verifyCode , verifyCode);
        }catch (Exception e){
            ResultModelUtil.fail(80007992,"服务错误");
        }
        return ResultModelUtil.success();
    }

    //根据邮件验证码登录
    @PostMapping("/emailLogin")
    public ResultModel emailCodeLogin(@RequestBody UserRegisterRequest userRegisterRequest , HttpServletRequest servletRequest , HttpServletResponse response) throws Exception {
        userRegisterRequest.setIp(WebUtil.requestIp(servletRequest));
        userRegisterRequest.setUa(WebUtil.requestUa(servletRequest));

        ResultModel<String> resultModel = userApiService.emailLogin(userRegisterRequest);
        if ("error".equals(resultModel.getData()))
        {
            return  ResultModelUtil.fail(848564,"邮箱验证码错误");
        }
        WebUtil.cookieAddSid(response , resultModel.getData());

        return ResultModelUtil.success(resultModel.getData());
    }

    //用户查看自己的信息
    @PostMapping("/getInformation")
    public ResultModel getSelfInformation(@Param("userId") Long userId,HttpServletRequest request)
    {
        //验证用户登录状态,得到登录用户的信息
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY , WebUtil.cookieGetSid(request));
        return userApiService.querySelfInformation(userId);
    }

    //用户修改头像 一次可以上传六张
    @PostMapping("/uploadMoreImg")
    public ResultModel uploadSixImg(List<MultipartFile> files , HttpServletRequest request) throws IOException {
        //验证用户登录状态 , 获取用户的登录信息
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY , WebUtil.cookieGetSid(request));
        if (files.size() > 6)
        {
            return ResultModelUtil.fail(MORE_MAX);
        }
        StringBuilder sb = new StringBuilder();
        int index = 0;
        //循环遍历 获取文件内容
        for (MultipartFile file : files)
        {
            index++;
            //获取文件内容
            InputStream is = file.getInputStream();
            //获取文件原始名
            String originName = file.getOriginalFilename() ;

            String fileType = file.getContentType(); //获取图片类型
            //判断图片是否符合类型
            boolean isAllowType = false;
            for(String allowType : ALLOW_TYPES)
            {
                if (fileType != null && fileType.contains(allowType))
                {
                    isAllowType = true;
                    break;
                }
            }
            CheckUtil.isFalse(isAllowType , ErrorCodeEn.FILE_UPLOAD_NOT_SUPPORT_IMG_TYPE);
            FileUploadImgRequest uploadImgRequest = null ;
            try
            {
                uploadImgRequest = FileUploadImgRequest.builder()
                        .base64(file.getBytes())
                        .fileName(originName)
                        .build();
            }
            catch (Exception e)
            {
                CheckUtil.isTrue(true , ErrorCodeEn.FILE_UPLOAD_FAIL);
            }
            //去把这一张图片存储到七牛云中
            ResultModel<String> linkFilename = fileApiService.uploadImg(uploadImgRequest);
            //存储完毕之后拼接
            if ( index < files.size() )
            {
                sb.append(linkFilename.getData()).append(" ");
            }
            if (index == files.size())
            {
                sb.append(linkFilename.getData());
            }
        }
        return userApiService.updateHeadImg(String.valueOf(sb));
    }

    //用户上传头像 每次只能上传一张  , 最多支持上传六张 , 上传的第一张作为头像
    @PostMapping("/updateAvatar3")
    public ResultModel uploadImg3(@RequestParam(value = "file") MultipartFile file , HttpServletRequest request) throws IOException, ParseException {
        //验证用户登录状态 , 获取用户的登录信息
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY, WebUtil.cookieGetSid(request));

        //上传之前,检查图片是否存在

        //查看用户上传的头像的数量 , 如果超过六张禁止上传
        ResultModel<Boolean> isAvatar = userApiService.queryAvatarCountService();
        try
        {
            if (!isAvatar.getData())
            {
                return ResultModelUtil.fail(MORE_MAX);
            }
        }
        catch (NullPointerException e)
        {
            return ResultModelUtil.fail(ErrorCodeEn.FILE_UPLOAD_FAIL);
        }
        //拿到用户上传的图片
        InputStream is = file.getInputStream();
        //获取文件原名
        String originName = file.getOriginalFilename();
        //获取图片类型
        String imgType = file.getContentType();
        //判断图片是否符合类型
        boolean isAllowType = false;
        for (String allowType : ALLOW_TYPES)
        {
            if(imgType != null && imgType.contains(allowType))
            {
                isAllowType = true;
                break;
            }
        }
        CheckUtil.isFalse(isAllowType , ErrorCodeEn.FILE_UPLOAD_NOT_SUPPORT_IMG_TYPE);
        FileUploadImgRequest uploadImgRequest = null;
        try
        {
            uploadImgRequest = FileUploadImgRequest.builder()
                    .base64(file.getBytes())
                    .fileName(originName)
                    .type(0) //用户上传图片此处恒为0 0 != -1 因此用户头像必须压缩
                    .build();
        }
        catch (Exception e)
        {
            CheckUtil.isTrue(true , ErrorCodeEn.FILE_UPLOAD_FAIL);
        }

        //去把这一张图片存储到阿里云中
        ResultModel<String> linkFilename = fileApiService.uploadImgOss(uploadImgRequest);

        //存储完毕 , 将图片保存到数据库
        if (linkFilename.getData() == null)
        {
            return  ResultModelUtil.fail(ErrorCodeEn.IMAGE_IS_NOPASS);
        }
        //检查同一个用户上传的图片是否重复
        ResultModel<Boolean> isSame = userApiService.selectSameAvatar(linkFilename.getData());
        if (isSame.getData())
        {
            return ResultModelUtil.fail(ErrorCodeEn.SAME_IMAGE);
        }

        return userApiService.uploadAvatar3("https://"+linkFilename.getData());
    }

    //用户删除头像列表中的图片
    @PostMapping("/deleteAvatar")
    public ResultModel deleteAvatarList(@RequestBody UserRegisterRequest avatar , HttpServletRequest request)
    {
        //验证用户登录状态 , 获取用户的登录信息
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY , WebUtil.cookieGetSid(request));
        //先把oss上的照片删除
        if (!fileApiService.deleteImgOss(avatar.getAvatar()).getSuccess())
        {
            //如果删除失败
            return ResultModelUtil.fail(ErrorCodeEn.NO_EXIST_IMAGE);
        }
        //更新数据库中的数据
        return userApiService.deleteAvatar(avatar.getAvatar());
    }

    //获取我点赞的帖子
    @PostMapping("/getMyLovePosts")
    public ResultModel<PageResponseModel<ArticleLoveResponse>> myLovePosts(HttpServletRequest request , @RequestBody PageRequestModel pageRequestModel) throws Exception {
        //验证用户登录状态 , 获取用户的登录信息
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY , WebUtil.cookieGetSid(request));
        return userApiService.selectMyLovePosts(pageRequestModel.getPageNo() , pageRequestModel.getPageSize());
    }

    //用户举报帖子
    @PostMapping("/informPosts")
    public ResultModel informPosts(HttpServletRequest request ,@RequestBody ArticleInformRequest articleInformRequest)
    {
        //验证用户登录状态 . 获取用户的登录信息
        request.setAttribute(Constant.REQUEST_HEADER_TOKEN_KEY , WebUtil.cookieGetSid(request));
        return userApiService.userInformPosts(articleInformRequest);
    }

}
